Copts and Robbers (c) 1981 Sirius *RESTORED and CRACKED*

Here's a cracked copy of the restored version of the Apple ][
game Copts and Robbers.

Track zero contains a modified version of LoGo's excellent
Snake Byte boot code. The level load routines were modified
to invoke the boot 2 disk read code.

The following bug fixes were also applied:

  * Fixed an uninitialized inventory item bug (!) that caused the
    game to crash if the first thing that the player touched was
    the treasure room wall.

    (t1 s8) 1000: 85 92 85 94 -> 20 64 1E EA        ;jsr bugfix
    (t2 sa) 1E64: 7 FF's -> 85 8f 85 92 85 94 60 F8 ;clear $8F & balance csum

  * Fixed an invalid branch operand bug (!) that caused the game
    to crash after successfully completing a level.

    (t2 sa) 1E39: D8 -> FB ;don't jump into an operand!

-Have phun!

[...Cracking Notes...]

Disc Map
--------
Tracks 1.5-F.5 use 4x4 nibble encoding - each track is a single "sector"
of $C00 bytes.

Read during disk boot:
    T0 S0     -> 0800-08FF (boot 1)
    T0 S1-4   -> 0400-07FF (boot 2)
    Track 1.5 -> 0800-13FF
    Track 2.5 -> 1400-1FFF
    Track 3.5 -> 4000-4BFF (title page part 1)
    Track 4.5 -> 4C00-57FF (title page part 2)
    Track 5.5 -> 5800-63FF (title page part 3, etc.)
    Track 6.5 -> 6400-6FFF
    Track 7.5 -> 7000-7BFF
    Track 8.5 -> 7C00-87FF
    Track 9.5 -> 8800-93FF
    Track A.5 -> 9400-9FFF (you win screen part 1, only used to calculate checksum)

Read during level load:
    Track A.5 -> 4000-4bff (you win screen part 1)
    Track B.5 -> 4c00-57ff (you win screen part 2)
    Track C.5 -> 5800-5fff (you win screen part 3, only 8 sectors)
    Track D.5 -> b000-bbff (level one)
    Track E.5 -> b000-bbff (level two)
    Track F.5 -> b000-bbff (level three)

Tracing the Boot Code
---------------------
; Load boot 1
9600<C600.C700M
96F9:59 FF
9600G
C0E8

; Get result of boot 1 checksum (same as Snake Byte)
; See http://www.hackzapple.com/phpBB2/viewtopic.php?t=123&sid=bb94b23229b7462bd47f13b629157f59
367<867.871M
370:03 20 DA FD 60
365:A2 00
365G
=> Result is #$20. Stack pointer will be set to this value.

; Load boot 2 code into 1400-17ff
810:14
84C:18
85D:EA EA
87E:59 FF
9659:18
96F9:01 08
9600G
C0E8

; Get result of 2nd checksum
35F<145F.1470M
35D:A9 20
370:20 DA FD 60
363:14
366:15
369:16
36C:17
35DG
=> Result is #$83. Pushed to stack. Used to calculate game start address.

Tracing the Game Load
---------------------
; Boot 2 patcher
9800:48                        ; Save accum.
    :A9 8D                     ; Install patch to:
    :8D 4A 05                  ;
    :8D 4E 05                  ;
    :A9 03 8D 4C 05            ;   Store byte at $360
    :A9 68 8D 4D 05            ;   Pop byte from stack
    :A9 61 8D 4F 05            ;   Store byte at $361
    :A9 03 8D 50 05
    :A9 4C 8D 51 05            ;   Jump to monitor
    :A9 59 8D 52 05            ;   ""
    :A9 FF 8D 53 05            ;   ""
    :A9 AB 8D 54 05            ;   Balance checksum with #$AB
    :68                        ; Restore accum.
    :4C 00 04                  ; Jump to boot 2

; Modify boot 0 to patch boot 1 to run the boot 2 patcher
9600<C600.C700M
96F8:A9 EA 8D 5D 08 8D 5E 08   ; Prevent boot 1 from clearing memory
    :A9 98 8D 7F 08            ; Jump to $9800 instead of $400
    :A9 0D 8D 80 08            ; Balance checksum
    :4C 01 08                  ; Jump to boot 1

; Run modified boot 0.
9600G

; Beep! In the monitor! Game start address is $833F+1.
360.361
=> Result is 3F 83

Game Routines/Data
------------------
008E: Player is holding an item (00=false, 01=true)
008F: Player inventory (00=key, 01=killer stone, 03=jewel, 06=ring, 07=vase, 08=magnet)
0400: Boot 2: Entry point
0490: Boot 2: Read a track
04D8: Boot 2: Move disk arm
0505: Boot 2: Draw the loading screen
054B: Boot 2: RTS to game start
0604: Boot 2: Loading screen bitmaps
0700: Boot 2: Loading screen HGR table
0770: Reset routine (multiple entry points)
07D0: Boot 2: Calculate checksum
0F6C: Level start
1B27: You win!
1E35: Level select menu
8340: Game start
8F00: Load N tracks. A=page, X=phases (trk * 2), Y=num tracks
8F1D: Sector count; normally #$0C, sometimes patched to #$08.
8FC0: Read data into buffer page specified by $01.

